﻿using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace Ocelot.ConsulExtensions
{
    /// <summary>
    /// 服务注册拓展(注册服务使用)
    /// </summary>
    public static class ConsulRegisterExtensions
    {
        /// <summary>
        /// 添加Consul注册
        /// </summary>
        /// <param name="services"></param>
        /// <param name="registration"></param>
        /// <returns></returns>
        public static IServiceCollection AddConsulRegister(this IServiceCollection services, AgentServiceRegistration registration)
        {
            services.AddHealthChecks();

            // 检查数据
            CheckConfig(registration);
            services.AddSingleton<AgentServiceRegistration>(registration);
            bool consulHostExist = registration.Meta.TryGetValue("ConsulHost", out string consulHost);
            if (!consulHostExist)
                throw new ArgumentNullException("ConsulHost not exist");

            services.AddSingleton<ConsulClient>(provider =>
            {
                AgentServiceRegistration registration = provider.GetRequiredService<AgentServiceRegistration>();
                bool consulHostExist = registration.Meta.TryGetValue("ConsulHost", out string consulHost);
                ConsulClient consulClient = new ConsulClient(conf =>
                {
                    conf.Address = new Uri(consulHost); //服务注册地址：集群中任意一个地址
                });
                return consulClient;
            });
            return services;
        }

        /// <summary>
        /// 启用consul注册
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static IApplicationBuilder UseConsulRegister(this IApplicationBuilder app)
        {
            app.UseHealthChecks("/health");

            AgentServiceRegistration registration = app.ApplicationServices.GetRequiredService<AgentServiceRegistration>();
            var consulClient = app.ApplicationServices.GetRequiredService<ConsulClient>();
            // 获取主机生命周期对象
            IHostApplicationLifetime lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
            // 服务启动后,向consul注册
            lifetime.ApplicationStarted.Register(async () =>
            {
                await consulClient.Agent.ServiceRegister(registration); // 注册到consul
            });
            // 程序停止时,向consul注销
            lifetime.ApplicationStopping.Register(async () =>
            {
                WriteResult writeResult = await consulClient.Agent.ServiceDeregister(registration.ID);
            });

            return app;
        }

        /// <summary>
        /// 检查配置文件
        /// </summary>
        /// <param name="serviceOptions"></param>
        private static void CheckConfig(AgentServiceRegistration registration)
        {
            if (string.IsNullOrEmpty(registration?.Address))
                throw new Exception("请正确配置Address");
            if (registration.Meta.TryGetValue("ConsulHost", out string consulHost) == false)
                throw new Exception("请在ConsulRegistrationMessage->Meta,添加ConsulHost属性");
            if (string.IsNullOrEmpty(registration.Check?.HTTP))
                throw new Exception("请在ConsulRegistrationMessage->Check->HTTP配置健康检查接口");
        }

    }
}